﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tracking.Data;
using Tracking.Data.Model;
using Tracking.Data.Model.Implementation;
using Tracking.Data.Model.Interfaces;
using Tracking.Web.Models;

namespace Tracking.Web.Controllers
{
    public class ShipmentController : Controller
    {

        ITrackingRepository trackingRepository;

        public ShipmentController()
            : this(new TrackingRepository())
        {

        }

        public ShipmentController(ITrackingRepository trackingRepository)
        {
            this.trackingRepository = trackingRepository;
        }



        //
        // GET: /Admin/

        public ActionResult Index()
        {
            return View("List");
        }


        public ActionResult List()
        {
            return View();
        }

        public ActionResult Create()
        {
            //<label class="error">@ViewBag.Error</label>

            return View(new ShipmentUIModel());
        }

        [HttpPost]
        public ActionResult Create(ShipmentUIModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    trackingRepository.Create(new Shipment()
                    {
                        TrackingNumber = model.TrackingNumber,
                        StartTimestamp = DateTime.Now
                    });

                    return RedirectToAction("List");
                }
                catch (Exception ex)
                {
                    AddError(ex.Message);
                }
            }
            return View(model);
        }

        public ActionResult Delete(int id)
        {
            var existingShipment = trackingRepository.GetById(id);
            ShipmentUIDeleteModel shipmentUImodel = new ShipmentUIDeleteModel()
            {
                TrackingNumber = existingShipment.TrackingNumber,
                Id = existingShipment.Id,
                State = ((ShipmentStates)existingShipment.State).ToString()
            };
            return View(shipmentUImodel);
        }

        [HttpPost]
        public ActionResult Delete(ShipmentUIDeleteModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    trackingRepository.Delete(model.Id);
                    return RedirectToAction("List");
                }
                catch (Exception ex)
                {
                    AddError(ex.Message);
                }
            }
            return View(model);
        }


        public ActionResult Edit(int id)
        {
            var existingShipment = trackingRepository.GetById(id);

            //get the possible states
            var selectList = BuildStateList(existingShipment);

            ShipmentUIModel shipmentUImodel = new ShipmentUIModel()
            {
                TrackingNumber = existingShipment.TrackingNumber,
                Id = existingShipment.Id,
                State = existingShipment.State,
                StateValues = selectList
            };

            return View(shipmentUImodel);
        }

        private List<SelectListItem> BuildStateList(Shipment existingShipment)
        {
            var selectList = GetSelectList();
            //select the current state
            var currentItem = selectList.First(p => p.Value == existingShipment.State.ToString());
            currentItem.Selected = true;
            return selectList;
        }

        [HttpPost]
        public ActionResult Edit(ShipmentUIModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    trackingRepository.Update(new Shipment()
                    {
                        TrackingNumber = model.TrackingNumber,
                        StartTimestamp = DateTime.Now,
                        Id = model.Id,
                        State = model.State
                    });

                    return RedirectToAction("List");
                }
                catch (Exception ex)
                {
                    AddError(ex.Message);
                }
            }
            else
            {
                AddError("invalid model");
            }
            return Edit(model.Id);
        }

        [HttpGet]
        public JsonResult Search(string trackingNumber)
        {
            Shipment result = trackingRepository.GetByTrackingNumber(trackingNumber);
            if (result == null)
            {
                return null;
            }
            ShipmentUISearchModel uiResultModel = new ShipmentUISearchModel()
            {
                Id = result.Id,
                State = ((ShipmentStates)result.State).ToString(),
                TrackingNumber = result.TrackingNumber,
                StartTimestamp = FormatDateTime(result.StartTimestamp),
                LastUpdateTimestamp = FormatDateTime(result.LastUpdatedTimestamp)
            };
            return Json(uiResultModel, JsonRequestBehavior.AllowGet);
        }


        #region private
        private List<SelectListItem> GetSelectList()
        {
            List<SelectListItem> list = new List<SelectListItem>();
            var values = Enum.GetValues(typeof(ShipmentStates));
            foreach (var item in values)
            {
                AddItem(list, item);
                //switch ((ShipmentStates)item)
                //{
                //    case ShipmentStates.Finalized:
                //        AddItem(list, item);
                //        break;
                //    case ShipmentStates.OnGoing:
                //        break;
                //    case ShipmentStates.Started:
                //        break;
                //}
            }
            return list;
        }

        #endregion
        private static void AddItem(List<SelectListItem> list, object item)
        {
            list.Add(new SelectListItem() { Text = item.ToString(), Value = ((byte)item).ToString(), Selected = false });
        }

        [HttpGet]
        public object GetGridModel(string sidx, string sord, int page, int rows, bool _search, string searchField = "", string searchOper = "", string searchString = "")
        {
            int total = 0;
            var trackingList = trackingRepository.Get(out total, page, rows, null, sidx).ToList();
            List<ShipmentGridModel> gridModel = new List<ShipmentGridModel>();
            foreach (var item in trackingList)
            {
                gridModel.Add(new ShipmentGridModel()
                {
                    Id = item.Id,
                    TrackingNumber = item.TrackingNumber,
                    Started = FormatDateTime(item.StartTimestamp),
                    LastUpdate = FormatDateTime(item.LastUpdatedTimestamp),
                    State = ((ShipmentStates)item.State).ToString(),
                });
            }
            var jqgridData = TojQgridFormat(gridModel, page, rows, total);
            var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(jqgridData, Newtonsoft.Json.Formatting.None);
            return jsonString;
        }

        internal JqGridUIModel TojQgridFormat(IEnumerable<object> list, int page, int pageSize, int totalRecords)
        {
            var pageIndex = page - 1;
            var totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
            return new JqGridUIModel
            {
                total = totalPages,
                page = page,
                records = totalRecords,
                rows = list.ToArray()
            };
        }

        private string FormatDateTime(DateTime? dt)
        {
            if (dt.HasValue)
            {
                return dt.Value.ToString("yyyy-MM-dd hh:mm:ss");
            }
            return "none";
        }
        private void AddError(string message)
        {
            ViewBag.Error = message;
            ViewData["Error"] = message;
        }

    }

    public class SearchObj
    {
        public string TrackingNumber { get; set; }
    }
}
